#include "registerdialog.h"
#include "ui_registerdialog.h"
#include <QRegularExpression>
#include "global.h"
#include "httpmgr.h"
#include <QTime>

RegisterDialog::RegisterDialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::RegisterDialog)
    , _countdown(10)
{
    initHttpHandlers();
    ui->setupUi(this);

    //构造定时器，切换到登录界面
    _countdown_timer=new QTimer(this);

    //注册调用事件的回调函数,负责定时
    connect(_countdown_timer,&QTimer::timeout,[this](){

        //注册会第哦啊
        if(_countdown==0)
        {
            _countdown_timer->stop();

            //发出切换命令：切换到登陆界面
            emit sigSwitchLogin();
            return ;
        }

        _countdown--;
        //显示倒计时
        auto str=QString("注册成功，%1 s后返回登录界面").arg(_countdown);
        ui->textLabel_return->setText(str);
    });

    ui->pass_edit->setEchoMode(QLineEdit::Password);
    ui->confirm_edit->setEchoMode(QLineEdit::Password);

    //连接信号处理槽函数
    connect(HttpMgr::GetInstance().get(), &HttpMgr::sig_reg_mod_finish, this, &RegisterDialog::slot_reg_mod_finish);

    //设定输入框输入后清空字符串
    ui->err_tip->clear();

    ///连接各个输入框输入结束之后事件(信号)的槽函数
    connect(ui->user_edit,&QLineEdit::editingFinished,this,[this](){
        checkUserValid();
    });

    connect(ui->email_edit, &QLineEdit::editingFinished, this, [this](){
        checkEmailValid();
    });

    connect(ui->pass_edit, &QLineEdit::editingFinished, this, [this](){
        checkPassValid();
    });

    connect(ui->confirm_edit, &QLineEdit::editingFinished, this, [this](){
        checkConfirmValid();
    });

    connect(ui->vertify_edit, &QLineEdit::editingFinished, this, [this](){
        checkVarifyValid();
    });

    ui->pass_visible->setCursor(Qt::PointingHandCursor);
    ui->confirm_visible->setCursor(Qt::PointingHandCursor);

    //关联动画状态机和类对象内部动画状态机
    ui->pass_visible->SetState("unvisible","unvisible_hover","","visible",
                               "visible_hover","");

    ui->confirm_visible->SetState("unvisible","unvisible_hover","","visible",
                                  "visible_hover","");

    //连接点击事件

    connect(ui->pass_visible, &ClickedLabel::clicked, this, [this]() {
        auto state = ui->pass_visible->GetCurState();
        if(state == ClickLbState::Normal){
            ui->pass_edit->setEchoMode(QLineEdit::Password);
        }else{
            ui->pass_edit->setEchoMode(QLineEdit::Normal);
        }
        qDebug() << "Label was clicked!";
    });

    connect(ui->confirm_visible, &ClickedLabel::clicked, this, [this]() {
        auto state = ui->confirm_visible->GetCurState();
        if(state == ClickLbState::Normal){
            ui->confirm_edit->setEchoMode(QLineEdit::Password);
        }else{
            ui->confirm_edit->setEchoMode(QLineEdit::Normal);
        }
        qDebug() << "Label was clicked!";
    });

}

RegisterDialog::~RegisterDialog()
{
    delete ui;
}

//注册后端返回。具体的客户端逻辑处理
//但是这里就是在做客户端的显示处
void RegisterDialog::initHttpHandlers()
{
    //注册获取验证码回包逻辑
    _handlers.insert(ReqId::ID_GET_VARIFY_CODE, [this](QJsonObject jsonObj){
        int error = jsonObj["error"].toInt();
        if(error != ErrorCodes::SUCCESS){

            if(error==ErrorCodes::UserExist)
            {
                showTip(tr("用户已存在"),false);
                return;
            }
            showTip(tr("参数错误"),false);
            return;
        }
        auto email = jsonObj["email"].toString();
        showTip(tr("验证码已发送到邮箱，注意查收"), true);
        qDebug()<< "email is " << email ;

    });


    //注册回调函数：处理用户注册函数
    _handlers.insert(ReqId::ID_REG_USER, [this](QJsonObject jsonObj){
        int error = jsonObj["error"].toInt();
        if(error != ErrorCodes::SUCCESS){
            showTip(tr("参数错误"),false);
            return;
        }
        auto email = jsonObj["email"].toString();
        showTip(tr("用户注册成功"), true);
        qDebug()<< "email is " << email ;

        //进行页面切换
        this->ChangeTipPage();
    });
}

//设置此时槽函数
void RegisterDialog::on_get_button_clicked()
{

    //获得结果，匹配正则表达式，根据正则表达式，设置状态，还有显示的字体
    auto email=ui->email_edit->text();
    QRegularExpression regex(R"((\w+)(\.|_)?(\w*)@(\w+)(\.(\w+))+)");

    auto match=regex.match(email).hasMatch();
    if(match)
    {
        //设置状态和显示字符，还有之后的发送验证那的逻辑
        //showTip(tr("验证码已经发送到邮箱，请注意查收"),match);

        //这里添加发送验证码的请求，发送到httpmgr，由其发送
        QJsonObject json_obj;
        json_obj["email"] = email;
        HttpMgr::GetInstance()->PostHttpreq(QUrl(gate_url_prefix+"/get_varifycode"),
                                            json_obj, ReqId::ID_GET_VARIFY_CODE,Modules::REGISTERMOD);
    }
    else
    {
        //设置错误并且刷新
        showTip(tr("邮箱地址不正确"),match);
    }

}

//可以设置显示文字的格式，通过match的值
void RegisterDialog::showTip(QString ss,bool match)
{
    if(match)
    {
        ui->err_tip->setText(ss);
        ui->err_tip->setProperty("state","normal");
    }
    else
    {
        ui->err_tip->setText(ss);
        ui->err_tip->setProperty("state","err");
    }
    repolish(ui->err_tip);
}

void RegisterDialog::AddTipErr(TipErr te, QString tips)
{
    //加入其中，显示
    _tip_errs.insert(te,tips);

    //如果有错误，当场就显示
    showTip(tips,false);
}

void RegisterDialog::DelTipErr(TipErr te)
{
    _tip_errs.remove(te);
    if(_tip_errs.empty())
    {
        //清除显示
        ui->err_tip->clear();
        return;
    }
    showTip(_tip_errs.first(),false);
}


//检查是否用户名复合规则
bool RegisterDialog::checkUserValid()
{
    if(ui->user_edit->text() == "")
    {
        AddTipErr(TipErr::TIP_USER_ERR, tr("用户名不能为空"));
        return false;
    }

    DelTipErr(TipErr::TIP_USER_ERR);
    return true;

}

bool RegisterDialog::checkEmailValid()
{
    //验证邮箱的地址正则表达式
    auto email = ui->email_edit->text();
    // 邮箱地址的正则表达式
    QRegularExpression regex(R"((\w+)(\.|_)?(\w*)@(\w+)(\.(\w+))+)");
    bool match = regex.match(email).hasMatch(); // 执行正则表达式匹配
    if(!match){
        //提示邮箱不正确
        AddTipErr(TipErr::TIP_EMAIL_ERR, tr("邮箱地址不正确"));
        return false;
    }

    DelTipErr(TipErr::TIP_EMAIL_ERR);
    return true;
}


bool RegisterDialog::checkVarifyValid()
{
    auto pass = ui->vertify_edit->text();
    if(pass.isEmpty()){
        AddTipErr(TipErr::TIP_VARIFY_ERR, tr("验证码不能为空"));
        return false;
    }

    DelTipErr(TipErr::TIP_VARIFY_ERR);
    return true;
}

//这只是检查是否空
bool RegisterDialog::checkAllInputNull()
{
    if(ui->user_edit->text()==""||ui->email_edit->text()==""||ui->pass_edit->text()==""||ui->confirm_edit->text()==""||ui->vertify_edit->text()=="")
    {
        return false;
    }
    else
    {
        return true;
    }
}

void RegisterDialog::ChangeTipPage()
{
    //切换page，同时启动定时器
    _countdown_timer->stop();
    ui->stackedWidget->setCurrentWidget(ui->page_2);
    _countdown_timer->start(1000);
}

bool RegisterDialog::checkPassValid()
{
    auto pass = ui->pass_edit->text();

    if(pass.length() < 6 || pass.length()>15){
        //提示长度不准确
        AddTipErr(TipErr::TIP_PWD_ERR, tr("密码长度应为6~15"));
        return false;
    }

    // 创建一个正则表达式对象，按照上述密码要求
    // 这个正则表达式解释：
    // ^[a-zA-Z0-9!@#$%^&*]{6,15}$ 密码长度至少6，可以是字母、数字和特定的特殊字符
    QRegularExpression regExp("^[a-zA-Z0-9!@#$%^&*]{6,15}$");
    bool match = regExp.match(pass).hasMatch();
    if(!match){
        //提示字符非法
        AddTipErr(TipErr::TIP_PWD_ERR, tr("不能包含非法字符"));
        return false;;
    }

    DelTipErr(TipErr::TIP_PWD_ERR);

    return true;
}

bool RegisterDialog::checkConfirmValid()
{
    if(ui->pass_edit->text()!=ui->confirm_edit->text())
    {
         AddTipErr(TipErr::TIP_CONFIRM_ERR, tr("两次输入密码不一致"));
        return false;
    }
    DelTipErr(TipErr::TIP_CONFIRM_ERR);
    return true;
}


//主要处理的是模块的逻辑，如果涉及到Req_ID ,那就发送到各个ID层去具体实现
//现在主要是负责模块的业务
//解析服务端发回来的消息
//同步交给各个各个模块去做
//也可以对ID进行区分，然后发送信号，异步调用
//类似于服务端的实现：使用map，映射 接口---->函数调用，通过查询mao，直接同步调用到后端的接口。
void RegisterDialog::slot_reg_mod_finish(ReqId id, QString res, ErrorCodes err)
{
    //这边传过来的如果不是Success,那就是其他的错误了，这部风职责就让Mod处理，所以下面重新解析具体的错误信息
    if(err != ErrorCodes::SUCCESS){
        showTip(tr("网络请求错误"),false);
        return;
    }

    // 解析 JSON 字符串,res需转化为QByteArray
    QJsonDocument jsonDoc = QJsonDocument::fromJson(res.toUtf8());
    //json解析错误
    if(jsonDoc.isNull()){
        showTip(tr("json解析错误"),false);
        return;
    }

    //json解析错误
    if(!jsonDoc.isObject()){
        showTip(tr("json解析错误"),false);
        return;
    }

    QJsonObject jsonObj = jsonDoc.object();


    //你说这里我能不能使用信号再去调用呢？
    //我觉的可以，发送一个ID的信号，专门到一个槽函数中，槽函数中专门调用进行处理
    //这个过程是异步进行的，唯一的不同是，这里是同步，而如果我那样做，就是一个异步过程
    //调用对应的逻辑

    //客户端主要逻辑处理，这里可以异步执行，使用信号发送到对应的界面处理
    _handlers[id](jsonDoc.object());




    return;

}

//注册界面确认的槽函数
void RegisterDialog::on_confirm_button_clicked()
{
    //如果一开始就提交，没有错误，也可以提交，不符合逻辑，如何修改，检查是否有输入进去，如果没有，不允许提交，检查任何一个输入框就可以
    //或者一开始就把所有的错误加入其中，但是不显示？不行，这不符合逻辑
    //或者提供一个标志位，只要检查到有任何一个字符，就不显示为NULL，放在所有输入结束之后进行动作，如果所有的删除了，那就变成null，就不会提交任何信息
    //使用第一种就行
    if(checkAllInputNull()==true)
    {
        //只要存在一个，那就可以进行接下来的逻辑，否则，直接显示为空，不可以提交
        //修改，所有测试通过才可以进行，否则不可以通过
        //也就是错误列表为空，如过不为空，就显示错误列表第一个
        if(_tip_errs.empty())
        {
            //创建JSON
            QJsonObject json_obj;
            json_obj["user"] = ui->user_edit->text();
            json_obj["email"] = ui->email_edit->text();
            json_obj["passwd"] = ui->pass_edit->text();
            json_obj["confirm"] = ui->confirm_edit->text();
            json_obj["varifycode"] = ui->vertify_edit->text();

            //叫欸HTTP管理器进行发送
            HttpMgr::GetInstance()->PostHttpreq(QUrl(gate_url_prefix+"/user_register"),
                                                json_obj, ReqId::ID_REG_USER,Modules::REGISTERMOD);
        }
        else
        {
            showTip(_tip_errs.first()+",不可以通讯服务端",false);
        }
    }
    else
    {
        showTip("存在空输入，拒绝提交！",false);
    }
}

void RegisterDialog::on_cancel_button_clicked()
{
    _countdown_timer->stop();
    emit sigSwitchLogin();
}


void RegisterDialog::on_returnButton_clicked()
{
    _countdown_timer->stop();
    emit sigSwitchLogin();
}

